import Taro, { Component } from '@tarojs/taro'
import { View, Image } from '@tarojs/components'
import EvoWaveLoading from '../evo-wave-loading'
import PanelController from './controller'
import { ReaderMode, ReaderData } from './utils/Consts'
import CacheManager from './manager/CacheManager'
import FlipManager, { PageImages, PageAnimations, PageAction } from './manager/FlipManager'
import AudioManager from './manager/AudioManager'
import './index.less'
interface EvoReaderProps {
    mode: ReaderMode
    data: ReaderData
    landscape: boolean
    useCache: boolean
}

interface EvoReaderState {
    isLoading: boolean
    loadPercent: number
    styles: {
        scene: {
            width: string, height: string, top: string, left: string
        },
        image: {
            width: string, height: string
        }
    },
    scaleMode: 'aspectFit' | 'widthFix',
    images: PageImages,
    animations: PageAnimations,
    bufferImg: string
    flipAction: PageAction

    showPanel: boolean
    playStatus: boolean
    page: number
    total: number
}

export default class EvoReader extends Component<EvoReaderProps, EvoReaderState> {

    isForceEnded: boolean = false

    cacheManager: CacheManager

    flipManager: FlipManager
    flipAnimationTimer: number

    audioManager: AudioManager

    autoActionTimer: number
    showPanelTimer: number

    constructor(props: EvoReaderProps) {
        super(props)
        this.state = {
            isLoading: false,
            loadPercent: 0,
            styles: {
                scene: {} as any,
                image: {} as any
            },
            scaleMode: 'widthFix',
            images: {
                before: '',
                current: '',
                after: ''
            },
            animations: {
                back: {},
                front: {},
                buffer: {}
            },
            bufferImg: '',
            flipAction: PageAction.None,
            showPanel: false,
            playStatus: false,
            page: 0,
            total: 0
        }
    }

    componentWillMount(): void {
        if (this.props.data.pages.length > 0) {
            this.setState({
                isLoading: true
            }, () => {
                this.initCacheManager()
            })
        }
    }

    setSceneLayout = () => {
        this.flipManager.getSceneLayout().then(({ width, height, top, left, scaleMode }) => {
            this.setState({
                styles: {
                    scene: { width, height, top, left },
                    image: { width, height }
                },
                scaleMode,
                page: this.flipManager.getPage(),
                total: this.flipManager.getTotal()
            }, () => {
                this.audioManager.play(this.flipManager.getPage())
            })
        })
    }

    replay = () => {
        this.flipManager.setPage(0)
        this.flipManager.init()
        this.audioManager.play(0)
    }

    destroy = () => {
        if (this.autoActionTimer) {
            clearTimeout(this.autoActionTimer)
        }
        if (this.flipManager) {
            this.flipManager.destroy()
        }
        if (this.audioManager) {
            this.audioManager.destroy()
        }
        if (this.cacheManager) {
            this.cacheManager.clear()
            this.cacheManager.destroy()
        }
    }

    render() {
        return (
            <View
                className={this.props.landscape ? 'evo-reader landscape' : 'evo-reader'}
                style={this.state.styles.scene}
            >
                <View
                    className='container'
                    onTouchStart={this.handleTouchStart}
                    onTouchMove={this.handleTouchMove}
                    onTouchEnd={this.handleTouchEnd}
                >
                    <View className='part half'>
                        <View className='left'>
                            <View className='img-wrap' style={this.state.styles.image}>
                                <Image hidden={!(this.state.flipAction === PageAction.Prev)} mode={this.state.scaleMode} src={this.state.images.before} style={this.state.styles.image} />
                                <Image hidden={(this.state.flipAction === PageAction.Prev)} mode={this.state.scaleMode} src={this.state.images.current} style={this.state.styles.image} />
                            </View>
                        </View>
                    </View>
                    <View className='part half right'>
                        <View className='right'>
                            <View className='img-wrap' style={this.state.styles.image}>
                                <Image hidden={!(this.state.flipAction === PageAction.Next)} mode={this.state.scaleMode} src={this.state.images.after} style={this.state.styles.image} />
                                <Image hidden={(this.state.flipAction === PageAction.Next)} mode={this.state.scaleMode} src={this.state.images.current} style={this.state.styles.image} />
                            </View>
                        </View>
                    </View>
                    <View className='part back' style={this.state.animations.back}>
                        <View className='img-wrap'>
                            <Image mode={this.state.scaleMode} src={this.state.flipAction === PageAction.Next ? this.state.images.after : this.state.images.before} style={this.state.styles.image} />
                        </View>
                    </View>
                    <View className='part front' style={this.state.animations.front}>
                        <View className='img-wrap'>
                            <Image mode={this.state.scaleMode} src={this.state.images.current} style={this.state.styles.image} />
                        </View>
                    </View>
                    <View className='part' style={this.state.animations.buffer}>
                        <View className='img-wrap'>
                            <Image mode={this.state.scaleMode} src={this.state.bufferImg} style={this.state.styles.image} />
                        </View>
                    </View>
                </View>
                <PanelController
                    showed={this.state.showPanel}
                    value={this.state.page + 1}
                    maxVaue={this.state.total}
                    status={this.state.playStatus}
                    onStatusChanged={this.handlePanelStateChanged}
                />
                <EvoWaveLoading
                    isShowed={this.state.isLoading}
                    isLandscape={false}
                    isShowText={true}
                    width={240}
                    height={240}
                    percent={this.state.loadPercent}
                    speed={0.5}
                    fontSize={26}
                    color='#00D1E5'
                    fontColor='#FFFFFF'
                    onLoadCompleted={this.handleLoadCompleted}
                />
            </View>
        )
    }

    /* ============================================
     * 页面事件，定义开始
     * ============================================ */
    handleTouchStart = (e: any) => {
        const { pageX, pageY } = e.changedTouches[0]
        this.flipManager.onTouchStartEvent({ x: pageX, y: pageY })
    }
    handleTouchMove = (e: any) => {
        // 如果用户手动，就清除自动翻转
        clearTimeout(this.autoActionTimer)
        const { pageX, pageY } = e.changedTouches[0]
        this.flipManager.onTouchMoveEvent({ x: pageX, y: pageY })
    }
    handleTouchEnd = (e: any) => {
        if (!this.flipManager.onTouchEndEvent()) {
            this.setState({
                showPanel: true
            }, () => {
                clearTimeout(this.showPanelTimer)
                this.showPanelTimer = setTimeout(() => {
                    this.setState({
                        showPanel: false
                    })
                }, 6000)
            })
        } else {
            // 如果用户手动，就清除自动翻转
            clearTimeout(this.autoActionTimer)
        }
        if (this.flipManager.isTouchEvent()) {
            e.stopPropagation()
        }
    }
    handlePanelStateChanged = (status: boolean) => {
        if (status) {
            this.setState({
                playStatus: status
            })
            const index = this.flipManager.getPage()
            this.audioManager.play(index)
        } else {
            this.audioManager.pause()
        }
    }
    handleLoadCompleted = () => {
        this.setState({
            isLoading: false
        }, () => {
            this.initAudioManager()
            this.initFlipManager()
            this.setSceneLayout()
        })
    }
    /* ============================================
     * 页面事件，定义结束
     * ============================================ */

    /* ============================================
     * 缓存管理器，定义开始
     * ============================================ */
    initCacheManager = () => {
        const images = this.props.data.pages.map((item) => {
            return item.image
        })
        this.cacheManager = new CacheManager(images, {
            onProgress: this.onCacheProgress
        })
        this.cacheManager.setUseCache(this.props.useCache)
        this.cacheManager.load(0)
    }

    onCacheProgress = (value: number) => {
        this.setState({
            loadPercent: value
        })
    }
    /* ============================================
     * 缓存管理器，定义结束
     * ============================================ */

    /* ============================================
     * 翻页管理器，定义开始
     * ============================================ */
    /**
     * 初始化翻页管理器
     */
    initFlipManager = () => {
        const images = this.props.data.pages.map((item) => {
            return item.image
        })
        this.flipManager = new FlipManager(images, this.props.landscape)
        this.flipManager.setDataChangedListener(this.onFlipDataChanged)
        this.flipManager.setAnimationChangedListener(this.onFlipAnimationChanged)
        this.flipManager.setAnimationListener({
            start: this.onFlipAnimationStart,
            end: this.onFlipAnimationEnd
        })
        this.flipManager.setCacheManager(this.cacheManager)
        this.flipManager.init()
    }

    /**
     * 翻书图片改变回调
     * @param images 图片数据
     */
    onFlipDataChanged = (images: PageImages) => {
        this.setState({
            images
        })
    }

    /**
     * 翻书动画改变回调
     * @param animations 动画数据
     */
    onFlipAnimationChanged = (animations: PageAnimations) => {
        this.setState({
            animations: { ...this.state.animations, ...animations }
        })
    }

    /**
     * 翻书动画 开始回调
     * @param flipAction 翻书动作，向前 或 向后
     */
    onFlipAnimationStart = (flipAction: PageAction) => {
        this.audioManager.pause()
        let bufferImg = this.state.images.current
        if (flipAction === PageAction.Prev) {
            bufferImg = this.state.images.before
        } else if (flipAction === PageAction.Next) {
            bufferImg = this.state.images.after
        }
        this.setState({
            flipAction,
            bufferImg
        })
    }

    /**
     * 翻书动画 结束回调
     * @param isFirst 翻书到首页 true false
     * @param isLast 翻书到末页 true false
     */
    onFlipAnimationEnd = (isPlay: boolean, isAllEnd: boolean) => {
        this.setState({
            flipAction: PageAction.None,
            page: this.flipManager.getPage()
        }, () => {
            if (!this.isForceEnded && isAllEnd) {
                if (isPlay) {
                    this.audioManager.play(this.state.page)
                    if (!this.cacheManager.isComplete()) {
                        this.cacheManager.load(this.state.page)
                    }
                } else {
                    if (this.flipManager.isFirst()) {
                        // this.audioManager.setPlayIndex(this.flipManager.getPage())
                        // this.audioManager.play()
                    } else if (this.flipManager.isLast()) {
                        // this.audioManager.stop()
                        // Taro.showToast({
                        //     title: '最后一页',
                        //     icon: 'success',
                        //     mask: true
                        // })
                    }
                }
            }
        })
    }
    /* ============================================
     * 翻页管理器，定义结束
     * ============================================ */

    /* ============================================
     * 音频管理器，定义开始
     * ============================================ */
    initAudioManager = () => {
        const audios = this.props.data.pages.map((item) => {
            return item.audio
        })
        this.audioManager = new AudioManager(
            this.props.data.name,
            '未来媒体',
            audios[0],
            audios
        )
        this.audioManager.setPlayIndex(-1)
        this.audioManager.setAudioListener({
            onPlay: this.onAudioPlay,
            onPause: this.onAudioPause,
            onStop: this.onAudioStop,
            onEnded: this.onAudioEnded,
            onError: this.onAudioError,
            onNotExists: this.onAudioNotExists
        })
    }

    onAudioPlay = () => {
        this.setState({
            playStatus: true
        })
    }
    onAudioPause = () => {
        this.setState({
            playStatus: false
        })
    }
    onAudioStop = () => {
        this.setState({
            playStatus: false
        })
    }
    onAudioEnded = () => {
        this.setState({
            playStatus: false
        }, () => {
            if (this.props.mode === ReaderMode.AUTO) {
                if (this.flipManager.hasNext()) {
                    this.autoActionTimer = setTimeout(() => {
                        this.flipManager.goActionAnimation(PageAction.Next)
                    }, 1500)
                }
            }
        })
    }
    onAudioError = () => {
        this.setState({
            playStatus: false
        })
    }
    onAudioNotExists = () => {
        this.setState({
            playStatus: false
        }, () => {
            if (this.props.mode === ReaderMode.AUTO) {
                if (this.flipManager.hasNext()) {
                    this.autoActionTimer = setTimeout(() => {
                        this.flipManager.goActionAnimation(PageAction.Next)
                    }, 3000)
                }
            }
        })
    }
    /* ============================================
     * 音频管理器，定义结束
     * ============================================ */
}
